home *** CD-ROM | disk | FTP | other *** search
- #include "ufk.h"
-
- int offset, /* Offset in data buffer to start */
- org_size; /* Original packet size */
- char size_lowered; /* Flag if packet shortening has been done */
-
- sendfile()
- {
- if (numprm <= 1) /* check parameter */
- prterr(ER_FSPCREQ);
- else if (!get_file_spec(TRUE)) /* Get filespec for send */
- prterr(ER_NOFILSEL);
- else
- {
- if (!open_port(TRUE,FALSE)) /* Setup communication port */
- prterr(ER_POPNERR);
- else
- {
- if (alloc_pkt(SEND)) /* Allocate packet memory */
- {
- sflg++;
- set_frame();
- if (!sendsw()) /* Send the file(s) */
- disp(0,18,"Send failed.\n"); /* Report failure */
- beep();
- while (get_file_spec(FALSE)); /* Flush directory buffer */
- }
- close_port(sflg,FALSE);
- }
- }
- }
-
- /*
- * s e n d s w
- *
- * Sendsw is the state table switcher for sending files. It loops until
- * either it finishes, or an error is encountered. The routines called
- * by sendsw are responsible for changing the state.
- *
- */
-
- sendsw()
- {
- char sinit(), sfile(), sattr(), sdata(), seof(), sbreak();
-
- init_xfer(); /* Reset counters */
- set_default_comm(); /* Set communication parameters */
- state = 'S'; /* Send initiate is start state */
- n = 0; /* Initialize message number */
- offset = 0; /* Offset in data buffer to start */
- size_lowered = FALSE; /* No long packet error received */
- numtry = 0; /* Say no tries yet */
- if (remote && (sflg != 2)) /* Wait before sending if remote */
- kdelay(send_delay); /* and if no server mode request */
- purgeline(ttyfd); /* Eat old input */
- while(TRUE) /* Do this as long as necessary */
- {
- if (debug)
- {
- prtdbgf("Send state: ");
- if (!screen)
- fputs("Send state: ",stdout);
- disp_state(50,13,state);
- }
- switch(state)
- {
- case 'S': /* Send-init */
- state = sinit();
- break;
-
- case 'F': /* Send-file */
- state = sfile();
- break;
-
- case 'A': /* Send attributes */
- state = sattr();
- break;
-
- case 'D': /* Send-data */
- state = sdata();
- break;
-
- case 'Z': /* Send-End-of-File */
- state = seof();
- break;
-
- case 'B': /* Send-Break */
- state = sbreak();
- break;
-
- case 'C': /* Complete */
- fin_xfer();
- return (TRUE);
-
- case 'Q':
- default: /* Unknown or abort, fail */
- fin_xfer();
- return (FALSE);
- }
- }
- }
-
-
- /*
- * s i n i t
- *
- * Send Initiate: send this host's parameters and get other side's back.
- */
-
- char sinit()
- {
- char num; /* Packet number */
- int len; /* length */
-
- if (numtry++ >= maxtry) /* If too many tries, give up */
- return('Q');
- spar(sndpkt,&len); /* Fill up init info packet */
-
- spack('S',n,len,sndpkt,0,1); /* Send an S packet */
- switch(rpack(&len,&num,recpkt,1)) /* What was the reply? */
- {
- case 'N': /* NAK, try it again */
- return(state);
-
- case 'Y': /* ACK */
- if (n != num) /* If wrong ACK, stay in S state */
- return(state); /* and try again */
- rpar(recpkt,len); /* Get other side's init info */
- numtry = 0; /* Reset try counter */
- n = ( n + 1) % 64; /* Bump packet count */
- return('F'); /* OK, switch state to F */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- return('Q'); /* Abort */
-
- case 'T': /* Timeout */
- if (aborted)
- return('Q'); /* aborted by user */
- case FALSE: /* Receive failure, try again */
- return(state);
-
- default: /* Anything else, just "abort" */
- return('Q');
- }
- }
-
-
- /*
- * s f i l e
- *
- * Send File Header.
- */
-
- char sfile()
- {
- char num, /* Packet number */
- fnm[15];
- int i, len; /* length */
-
- if (numtry++ >= maxtry) /* If too many tries, give up */
- return('Q');
-
- aborted = FALSE;
- if (fp != ERROR) /* If left open, close it */
- fclose(fp);
- fp = fopen(filnam,"r"); /* open the file to be sent */
- if (fp == NULL) /* If bad file pointer, give up */
- {
- error(PER_OPEN,"%s",filnam); /* Can't open file */
- if (!get_file_spec(FALSE))
- return('C'); /* No more files to do */
- else
- return('S'); /* Try next file */
- }
- for (i = strlen(filnam) - 1; i >= 0; --i)
- if (filnam[i] == '/') /* Skip directory specification */
- break;
- strcpy(fnm,&filnam[i+1]);
- map_case(fnm,OUT); /* map to correct case */
- if (!nooutput)
- {
- if (screen)
- {
- disp(0,2,"Sending: ");
- posit(20,2);
- printf("%s as %s", filnam, fnm);
- clreol(-1,-1);
- }
- else
- printf("\n\lSending: %s as %s\n\l",filnam,fnm);
- }
- fnm[strlen(fnm)] = EOF; /* Terminate data */
- len = bufill(sndpkt,TRUE,fnm);
- spack('F',n,len,sndpkt,0,block_check_type); /* Send an F packet */
- switch(rpack(&len,&num,recpkt,block_check_type))/* What was the reply? */
- {
- case 'N': /* NAK, just stay in this state, */
- num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */
- if (n != num) /* which is just like an ACK for */
- return(state); /* this packet so fall thru to... */
-
- case 'Y': /* ACK */
- if (n != num) /* If wrong ACK, stay in F state */
- return(state);
- numtry = 0; /* Reset try counter */
- n = (n + 1) % 64; /* Bump packet count */
- if (attribute)
- return('A'); /* Switch to attribute state */
- else
- {
- if ((size = bufill(sndpkt,TRUE,0)) == EOF)/* data from file */
- return('Z'); /* If EOF then empty data file */
- org_size = size; /* Remember original size */
- return('D'); /* Switch state to D */
- }
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- return('Q'); /* abort */
-
- case 'T': /* Timeout */
- if (aborted)
- {
- error(PER_ABORTED); /* send error packet */
- return('Q'); /* aborted by user */
- }
- case FALSE: /* Receive failure, stay in F */
- return(state);
-
- default: /* Something else, just "abort" */
- return('Q');
- }
- }
-
- /*
- * s a t t r
- *
- * Send File Attributes
- */
-
- char sattr()
- {
- char num; /* Packet number */
- int len; /* length */
-
- if (numtry++ >= maxtry) /* If too many tries "abort" */
- return('Q');
-
- snd_attributes(); /* Prepare send attribute packet */
- spack('A',n,size,sndpkt,0,block_check_type);/* Send an A packet */
- switch (rpack(&len,&num,recpkt,block_check_type))/* What was the reply? */
- {
- case 'N': /* NAK, just stay in this state, */
- num = (--num < 0 ? 63 : num); /* unless NAK for previous packet, */
- if (n != num) /* which is just like an ACK for */
- return(state); /* this packet so fall thru to... */
-
- case 'Y': /* ACK */
- if (n != num) /* If wrong ACK, fail */
- return(state);
- numtry = 0; /* Reset try counter */
- n = (n + 1) % 64; /* and bump packet count */
- if ((size = bufill(sndpkt,TRUE,0)) == EOF)/* Get data from file */
- return('Z'); /* If EOF then empty data file */
- org_size = size; /* Remember original size */
- return('D'); /* Switch state to data */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- return('Q'); /* abort */
-
- case 'T': /* Timeout */
- if (aborted)
- {
- error(PER_ABORTED); /* send error packet */
- return('Q'); /* aborted by user */
- }
- case FALSE: /* Receive failure, stay in B */
- return(state);
-
- default: /* Other, "abort" */
- return ('Q');
- }
- }
-
-
- /*
- * s d a t a
- *
- * Send File Data
- */
-
- char sdata()
- {
- char num, /* Packet number */
- tmpc;
- int len; /* length */
-
- if (numtry++ >= maxtry) /* If too many tries, give up */
- return('Q');
- spack('D',n,size,sndpkt,offset,block_check_type);/* Send a D packet */
- switch(rpack(&len,&num,recpkt,block_check_type))/* What was the reply? */
- {
- case 'N': /* NAK, just stay in this state, */
- num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */
- if (n != num) /* which is just like an ACK for */
- { /* this packet so fall thru to 'Y' */
- if ((org_size > 91) && auto_recover)/* If extended length... */
- lower_size(); /* Lower packet size on error */
- return(state); /* Try again */
- }
-
- case 'Y': /* ACK */
- if (n != num) /* If wrong ACK, fail */
- return(state);
- numtry = 0; /* Reset try counter */
- n = (n + 1) % 64; /* Bump packet count */
- if (size_lowered)
- adjust_size(); /* Still data in buffer */
- else
- {
- offset = 0; /* No more old data in buffer */
- if ((size = bufill(sndpkt,FALSE,0)) == EOF)/* Get new data */
- return('Z'); /* If EOF set state to that */
- org_size = size; /* Remember original size */
- }
- tmpc = *recpkt;
- if (len == 1) /* Data on ack */
- {
- if (tmpc == 'Z') /* Stop entire batch */
- filecount = 0; /* No more files to send */
- if ((tmpc == 'X') || (tmpc == 'Z'))
- aborted = tmpc - 64; /* Make binary */
- }
- if ((aborted == ABORTX) || (aborted == ABORTZ))
- {
- if (screen)
- disp(0,19,"Transfer interrupted.");
- else
- fputs("Transfer interrupted.\n\l",stdout);
- beep();
- return('Z'); /* Send abort */
- }
- return('D'); /* Got data, stay in state D */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- return('Q'); /* abort */
-
- case 'T': /* Timeout */
- if (aborted)
- {
- error(PER_ABORTED); /* send error packet */
- return('Q'); /* aborted by user */
- }
- if ((org_size > 91) && auto_recover) /* If extended length... */
- lower_size(); /* Lower packet size on error */
-
- case FALSE: /* Receive failure, stay in D */
- return(state);
-
- default: /* Anything else, "abort" */
- return('Q');
- }
- }
-
-
- /*
- * s e o f
- *
- * Send End-Of-File.
- */
-
- char seof()
- {
- char num; /* Packet number */
- int len, tlen; /* length */
-
- if (numtry++ >= maxtry) /* If too many tries, "abort" */
- return('Q');
-
- tlen = 0; /* Assume no abort */
- if ((aborted == ABORTX) || (aborted == ABORTZ))
- {
- *sndpkt = 'D'; /* Discard file on abort */
- tlen = 1;
- *(sndpkt+sizeof(char)) = '\0'; /* For debug printout */
- }
- spack('Z',n,tlen,sndpkt,0,block_check_type); /* Send a 'Z' packet */
- switch(rpack(&len,&num,recpkt,block_check_type))/* What was the reply? */
- {
- case 'N': /* NAK, just stay in this state, */
- num = (--num < 0 ? 63 : num); /* unless it's NAK for next packet */
- if (n != num) /* which is just like an ACK for */
- return(state); /* this packet so fall thru to... */
-
- case 'Y': /* ACK */
- if (n != num) /* If wrong ACK, hold out */
- return(state);
- numtry = 0; /* Reset try counter */
- n = (n + 1) % 64; /* and bump packet count */
- fclose(fp); /* Close the input file */
- fp = ERROR; /* flag no file open */
-
- if (!get_file_spec(FALSE))
- return ('B'); /* Stop if no more files */
- if (aborted == ABORTZ) /* Abort the rest ? */
- {
- while (get_file_spec(FALSE)); /* Flush directory buffer */
- return ('B');
- }
- return('F'); /* More files, switch state to F */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- return('Q'); /* abort */
-
- case 'T': /* Timeout */
- if (aborted)
- {
- error(PER_ABORTED); /* send error packet */
- return('Q'); /* aborted by user */
- }
- case FALSE: /* Receive failure, stay in Z */
- return(state);
-
- default: /* Something else, "abort" */
- return('Q');
- }
- }
-
-
- /*
- * s b r e a k
- *
- * Send Break (EOT)
- */
-
- char sbreak()
- {
- char num; /* Packet number */
- int len; /* length */
-
- if (numtry++ >= maxtry) /* If too many tries "abort" */
- return('Q');
-
- spack('B',n,0,sndpkt,0,block_check_type);/* Send a B packet */
- switch (rpack(&len,&num,recpkt,block_check_type))/* What was the reply? */
- {
- case 'N': /* NAK, just stay in this state, */
- num = (--num < 0 ? 63 : num); /* unless NAK for previous packet, */
- if (n != num) /* which is just like an ACK for */
- return(state); /* this packet so fall thru to... */
-
- case 'Y': /* ACK */
- if (n != num) /* If wrong ACK, fail */
- return(state);
- numtry = 0; /* Reset try counter */
- n = (n + 1) % 64; /* and bump packet count */
- return('C'); /* Switch state to Complete */
-
- case 'E': /* Error packet received */
- prerrpkt(recpkt); /* Print it out and */
- return('Q'); /* abort */
-
- case 'T': /* Timeout */
- if (aborted)
- {
- error(PER_ABORTED); /* send error packet */
- return('Q'); /* aborted by user */
- }
- case FALSE: /* Receive failure, stay in B */
- return(state);
-
- default: /* Other, "abort" */
- return ('Q');
- }
- }
-
- lower_size()
- {
- int rest;
-
- if (size >= 80) /* Minimum size to cut packet size to */
- {
- rest = size % 2; /* Find out if odd or even */
- size /= 2; /* Half of it */
- size += rest; /* Add rest if odd */
- spsiz = size; /* Use the new size from now on */
- size_lowered = TRUE; /* Flag size has been modified */
- check_prefix(); /* Make sure not in middle of prefix sequence */
- }
- }
-
- adjust_size()
- {
- offset += size; /* Increment offset to next unsend character */
- if (offset + size >= org_size) /* Adjust size if past end of buffer */
- {
- size = org_size - offset;
- size_lowered = FALSE; /* Flag modification done */
- }
- else
- check_prefix(); /* Make sure not in middle of prefix sequence */
- }
-
- check_prefix()
- {
- register char *p;
- char *q;
-
- p = sndpkt + offset; /* Start check at this place */
- q = p + size; /* Until end of current window */
- while (p < q)
- {
- if (*p == repeat_quote) /* If it's a repeat quote character .. */
- p += 2 * sizeof(char); /* Skip count */
- if (*p == eight_quote) /* If it's an eight-bit quote */
- p++; /* Skip it */
- if (*p == quote) /* Same for control quote character */
- p++;
- p++; /* Point to next data character */
- }
- size = p - (sndpkt + offset); /* Calculate new size */
- }
-